from ctypes import *
from my_debugger_defines import * 
kernel32 = windll.kernel32

class debugger():
    def __init__(self):
        #pass
        self.h_process = None
        self.pid = None
        self.debugger_active = False        
    
    def load(self,path_to_exe):
        #dwCreation flag, declared in _defines determines how to create the fing process
        #you should set creation_flags = CREATE_NEW_CONCOLE if you want to see the executable gui
        #creation_flags = CREATE_NEW_CONSOLE
        creation_flags = DEBUG_PROCESS
        
        #instantiate the structs
        startupinfo = STARTUPINFO()
        process_information = PROCESS_INFORMATION()
        
        #the following two option will allow the started process to be shown as a separate window
        startupinfo.dwFlags = 0x1
        startupinfo.wShowWindow = 0x0
        
        #we then instantiate the cb variable in the STARTUPINFO struct which is just the size of the struct itself
        startupinfo.cb = sizeof(startupinfo)
        if kernel32.CreateProcessA(path_to_exe,
                                   None,
                                   None,
                                   None,
                                   None,
                                   creation_flags,
                                   None,
                                   None,
                                   byref(startupinfo),
                                   byref(process_information)):
            print "[*] We have launched the process !!!"
            print "[*] PID: %d" % process_information.dwProcessId
            print "[*] Thread: %d" % process_information.dwThreadId
            
            #obtain a valid handle to the newly created process
            #and store it for future access
            self.h_process = self.open_process(process_information.dwProcessId)
        
        else:
            print "[*] Something has gone seriously wrong..."
            print "[*] Error: 0x%08x." % kernel32.GetLastError()
            
            
    def open_process(self,pid):
        h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS,False,pid)
        print "[*] in open_process return h_process... h_process is: 0x%x" % h_process
        print "[*] in open_process Error: %s" % FormatError(kernel32.GetLastError())        
        print "[*] in open_process Error: 0x%08x." % kernel32.GetLastError()
        return h_process
    
    def attach(self,pid):
        self.h_process = self.open_process(pid)
        #we attempt to attach to the process... if this fails we exit the call
        print "[*] in attach return h_process... h_process is: 0x%x" % self.h_process        
        print "[*] in attach return h_pid... h_pid is: %d" % pid       
        if kernel32.DebugActiveProcess(pid):
            self.debugger_active = True
            self.pid = int(pid)
            print "1"
        else: 
            #print "[*] unable to attach to process... go figure..."
            print "[*] in attach Unable to attach to the process. %s" % FormatError(kernel32.GetLastError())
            print "[*] in attach Error: 0x%08x." % kernel32.GetLastError()
            
    def run(self):
        #now we have to poll the debugee for debugging events
        while self.debugger_active == True:
            self.get_debug_event()
            
    def get_debug_event(self):
        debug_event = DEBUG_EVENT()
        continue_status = DBG_CONTINUE
        
        if kernel32.WaitForDebugEvent(byref(debug_event),INFINITE):
            #we arent going to build any event handlers just yet. Lets just resume the process for now.
            raw_input("Press a key to cont...")
            self.debugger_active = False
            kernel32.ContinueDebugEvent( \
                                         debug_event.dwProcessId, \
                                         debug_event.dwThreadId, \
                                         continue_status)
    def detach(self):
        if kernel32.DebugActiveProcessStop(self.pid):
            print "[*] Finished debugging. now exiting..."
            return True
        else:
            print "Something has gone seriously wrong... again..."
            return False
        
